#include "core/widget.h"

namespace core
{
    BEGIN_ATTRIBUTE_MAP(StWidget)
        ATTRIBUTE(COMMON_CONTROL_PROPERTY_ID, StAttributeString, ATTRIBUTE_TRAIT_NULL)

        ATTRIBUTE_ENUM_BEGIN(COMMON_CONTROL_PROPERTY_VISIBLE, StAttributeBool)
            ATTRIBUTE_ENUM_VALUE("visible", true)
            ATTRIBUTE_ENUM_VALUE("hidden", false)
        ATTRIBUTE_ENUM_END(ATTRIBUTE_TRAIT_PAINT)

        ATTRIBUTE(COMMON_CONTROL_PROPERTY_TITLE, StAttributeWString, ATTRIBUTE_TRAIT_NULL)

        ATTRIBUTE_ENUM_BEGIN(COMMON_CONTROL_PROPERTY_TABSTOP, StAttributeBool)
            ATTRIBUTE_ENUM_VALUE("enable", true)
            ATTRIBUTE_ENUM_VALUE("disable", false)
        ATTRIBUTE_ENUM_END(ATTRIBUTE_TRAIT_NULL)

        ATTRIBUTE_ENUM_BEGIN(COMMON_CONTROL_PROPERTY_DRAG, StAttributeBool)
            ATTRIBUTE_ENUM_VALUE("enable", true)
            ATTRIBUTE_ENUM_VALUE("disable", false)
        ATTRIBUTE_ENUM_END(ATTRIBUTE_TRAIT_NULL)

        ATTRIBUTE(COMMON_CONTROL_PROPERTY_ZINDEX, StAttributeInteger, ATTRIBUTE_TRAIT_PAINT)

        ATTRIBUTE(COMMON_CONTROL_PROPERTY_ALPHA, StAttributeInteger, ATTRIBUTE_TRAIT_PAINT)

        CHAIN_MEMBER_ATTRIBUTE_MAP(style_normal_)
    END_ATTRIBUTE_MAP()

    StWidget::StWidget()
        : parent_(0)
        , prev_(0)
        , next_(0) {}

    StWidget::~StWidget() {}

    KeyWidget StWidget::Key()
    {
        KeyWidget key;
        std::string id;
        KeyAttribute attribute = StringToKeyAttribute(COMMON_CONTROL_PROPERTY_ID);
        if (GetAttribute(attribute, &id))
        {
            key = StringToKeyWidget(id);
        }

        return key;
    }

    bool StWidget::IsContainer() { return false; }

    StObject* StWidget::Clone()
    {
        StWidget* widget = new StWidget;
        if (!widget)
        {
            return 0;
        }

        CopyToWidget(widget);
        return widget;
    }

    void StWidget::Drop() { delete this; }

    StWidget* StWidget::HitTest(int x, int y) { return 0; }

    void StWidget::CopyToWidget(StWidget* target)
    {
        target->style_normal_ = style_normal_;
        target->style_hover_ = style_hover_;
        target->style_down_ = style_down_;

        target->rect_border_ = rect_border_;
        target->rect_content_ = rect_content_;
        target->action_state_ = action_state_;
    }

    bool StWidget::Parse(const XmlElement* element, const StStyleCache& cache)
    {
        if (!element)
        {
            return false;
        }

        return ParseAttribute(element, cache);
    }

    LRESULT StWidget::DispatchMessage(UINT umsg, WPARAM wparam, LPARAM lparam)
    {
        LRESULT result = 0;
        ProcessMessage(umsg, wparam, lparam, &result);

        return result;
    }

    bool StWidget::ParseAttribute(const XmlElement* element, const StStyleCache& cache)
    {
        std::string style;
        std::string class_name;

        const XmlAttribute *attribute = element->FirstAttribute();
        while (attribute)
        {
            const char *value = attribute->Value();
            const char *name = attribute->Name();
            if (!name)
            {
                continue;
            }

            if (strcmp("style", name) == 0)
            {
                style = value;
            }
            else if (strcmp("class", name) == 0)
            {
                class_name = value;
            }
            else
            {
                unsigned result = 0;
                ParseAttribute(name, value, result);
            }

            attribute = attribute->Next();
        }

        AnalyseStyle(style.c_str(), class_name.c_str(), cache);

        return true;
    }

    bool StWidget::AnalyseStyle(const char *value, const char *classname, const StStyleCache& cache)
    {
        cache.GetStyleByName(tag_name_, &style_normal_);

        std::string identifier = "";
        GetAttribute<std::string>(StringToKeyAttribute(COMMON_CONTROL_PROPERTY_ID), &identifier);
        StStyle style;
        if (cache.GetStyleById(identifier, &style))
        {
            style_normal_.Copy(style);
        }

        if (classname)
        {
            StStyle style;
            cache.GetStyleByClass(classname, &style);
            style_normal_.Copy(style);
        }

        if (value)
        {
            style_normal_.ParseValues(value);
        }

        return true;
    }
}